import { Injectable } from '@nestjs/common';
import { pinyin } from 'pinyin-pro';
import slugify from 'slugify';

@Injectable()
export class SharedService {
  /**
   * 构造树型结构数据
   */
  public handleTree(data: any[], id?: string, parentId?: string, children?: string) {
    const config = {
      id: id || 'id',
      parentId: parentId || 'parentId',
      childrenList: children || 'children',
    };

    const childrenListMap = {};
    const nodeIds = {};
    const tree = [];

    for (const d of data) {
      const parentId = d[config.parentId];
      if (childrenListMap[parentId] == null) {
        childrenListMap[parentId] = [];
      }
      nodeIds[d[config.id]] = d;
      childrenListMap[parentId].push(d);
    }

    for (const d of data) {
      const parentId = d[config.parentId];
      if (nodeIds[parentId] == null) {
        tree.push(d);
      }
    }

    for (const t of tree) {
      adaptToChildrenList(t);
    }

    function adaptToChildrenList(o) {
      if (childrenListMap[o[config.id]] !== null) {
        o[config.childrenList] = childrenListMap[o[config.id]];
      }
      if (o[config.childrenList]) {
        for (const c of o[config.childrenList]) {
          adaptToChildrenList(c);
        }
      }
    }

    return tree;
  }

  /**
   * 生成别名
   * @param name
   * @param isExist
   */
  public async createSlug(name: string, isExist: (slug: string) => Promise<boolean>) {
    const slug = this.convertSlug(name);
    if (!(await isExist(slug))) {
      return slug;
    }
    let count = 1;
    while (true) {
      const isExistSlug = await isExist(`${slug}-${count}`);
      if (isExistSlug) {
        count++;
      } else {
        return `${slug}-${count}`;
      }
    }
  }

  /**
   * 转换成别名，先转拼音再转别名
   * @param text
   * @private
   */
  private convertSlug(text: string) {
    const pinyinStr = pinyin(text, {
      type: 'string',
      separator: '-',
      toneType: 'num',
      nonZh: 'consecutive',
    });
    return slugify(pinyinStr, {
      replacement: '-', // 将空格替换为替换字符，默认为“-”
      remove: undefined, // 删除与正则表达式匹配的字符，默认为“undefined”
      lower: true, // 转换为小写，默认为“false”
      strict: true, // 去除除替换之外的特殊字符，默认为“false”
      locale: 'en', // 要使用的区域设置的语言代码
      trim: true, // 修剪前导和尾随替换字符，默认为“true”
    });
  }
}
